<template>
  <el-dialog title="编辑头像" v-model="visible" top="10vh" width="600px" :before-close="handleClose" :close-on-click-modal="false" :close-on-press-escape="false" append-to-body v-loading.fullscreen.lock="loading">
    <div class="avatar-cropper-wrapper">
      <div class="avatar-cropper">
        <el-upload accept="image/png, image/jpeg, image/jpg" action="" v-show="!imgUrl" :auto-upload="false" :show-file-list="false" :on-change="uploadClickEvent">
          <el-button ref="avatarUploadBtnRef" type="primary">选择图片</el-button>
        </el-upload>
        <vue-cropper ref="avatarCropperRef" v-show="imgUrl" :img="imgUrl" auto-crop fixed-box center-box :auto-crop-width="200" :auto-crop-height="200" @realTime="realTimeEvent"></vue-cropper>
      </div>
      <div class="avatar-preview">
        <div class="avatar-preview__item" v-for="item in previewStyle" :key="item.zooStyle" :style="item.style">
          <div v-show="imgUrl" :class="previews.div" class="avatar-preview__item-wrapper" :style="item.zoomStyle">
            <img :src="previews.url" :style="previews.img">
          </div>
        </div>
        <div class="avatar-preview__tips">
          <el-button type="text" v-if="imgUrl" @click="uploadPreviewEvent" size="medium">重新上传</el-button>
          <span v-else>预 览</span>
        </div>
      </div>
    </div>
    <template #footer>
      <el-button @click="handleClose">取消</el-button>
      <el-button type="primary" @click="confirmUpload">确认</el-button>
    </template>
  </el-dialog>
</template>

<script lang="ts">
import { defineComponent, ref, watch } from 'vue'
import { UPDATE_MODEL_EVENT } from '@/common/contants'
import { VueCropper } from 'vue-cropper'
import { fileUpload, OssApiResult } from '@/api/oss'

import 'vue-cropper/dist/index.css'
import { ElMessage } from 'element-plus'
import { ListResultData } from '@/common/types/apiResult.type'

export default defineComponent({
  components: { VueCropper },
  props: {
    modelValue: {
      type: Boolean,
      default: false
    },
    avatarUrl: {
      type: String,
      default: ''
    }
  },
  emits: [UPDATE_MODEL_EVENT, 'change'],
  setup (props, { emit }) {
    // dialog
    const visible = ref<boolean>(false)
    const handleClose = () => {
      emit(UPDATE_MODEL_EVENT, false)
    }

    const imgUrl = ref()
    watch(() => props.modelValue, (val: boolean) => {
      visible.value = val
      if (val) {
        imgUrl.value = props.avatarUrl
      }
    })

    const uploadClickEvent = (file: any) => {
      if ('image/png, image/jpeg, image/jpg'.indexOf(file.raw.type) === -1) {
        ElMessage({ type: 'error', message: '文件类型错误' })
        return false
      }
      if (file.raw.size > 1024 * 1024 * 5) {
        ElMessage({ type: 'error', message: '上传图片大小不能超过 5M' })
        return false
      }
      const reader = new FileReader()
      reader.readAsDataURL(file.raw)
      reader.onload = (e) => {
        imgUrl.value = e?.target?.result
      }
    }

    // 重新上传
    const avatarUploadBtnRef = ref()
    const uploadPreviewEvent = () => {
      avatarUploadBtnRef.value.$el.click()
    }

    // 实时预览
    const previews = ref({})
    const realTimeEvent = (data: any) => {
      previews.value = data
    }

    // 预览样式
    const previewStyle = [
      { style: { width: '108px', height: '108px', margin: '0 auto' }, zoomStyle: { zoom: 0.5 } },
      { style: { width: '68px', height: '68px', margin: '27px auto' }, zoomStyle: { zoom: 0.3 } },
      { style: { width: '48px', height: '48px', margin: '0 auto' }, zoomStyle: { zoom: 0.2 } }
    ]

    // 确认上传
    const avatarCropperRef = ref()
    // 获取裁剪后的图片数据
    const getCropBlob = (): Promise<Blob> => {
      return new Promise(resolve => {
        avatarCropperRef.value.getCropBlob((data: Blob) => {
          resolve(data)
        })
      })
    }
    const loading = ref<boolean>(false)
    const confirmUpload = async () => {
      loading.value = true
      const formData = new FormData()
      const cropData = await getCropBlob()
      formData.append('file', cropData)
      formData.append('business', '头像')
      const res = await fileUpload(formData)
      loading.value = false
      if (res?.code === 200) {
        const data = res.data as OssApiResult[]
        emit('change', data[0].url)
        handleClose()
      } else {
        ElMessage({ type: 'error', message: res?.msg || '网络异常，请稍后重试' })
      }
    }

    return {
      visible,
      handleClose,
      avatarUploadBtnRef,
      uploadClickEvent,
      imgUrl,
      previews,
      realTimeEvent,
      previewStyle,
      uploadPreviewEvent,
      avatarCropperRef,
      loading,
      confirmUpload
    }
  }
})
</script>

<style lang="scss" scoped>
.avatar-cropper-wrapper {
  display: flex;

  .avatar-cropper {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 400px;
    height: 400px;
    background-color: #F0F2F5;
    margin-right: 10px;
    border-radius: 4px;

  }

  .avatar-preview {
    width: 150px;
    height: 400px;
    background-color: #F0F2F5;
    border-radius: 4px;
    padding: 16px 0;

    &__item {
      display: flex;
      align-items: center;
      justify-content: center;
      border: 3px solid #fff;
      border-radius: 50%;

      &-wrapper {
        width: 200px;
        height: 200px;
        overflow: hidden;
        border-radius: 50%;
      }
    }

    &__tips {
      text-align: center;
      margin-top: 50px;
      font-size: 14px;
      color: #666;
    }
  }
}
</style>
